﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Castle.Core;
using Microsoft.Practices.ServiceLocation;
using Castle.Windsor;
using System.Collections;

namespace MetaContainer.Castle
{
   /// <summary>
   /// Adapter for MetaContainer using Castle's Windsor as implementation of <see cref="IMetaContainer"/>.
   /// </summary>
   public sealed class CastleWindsorMetaContainerAdapter : ServiceLocatorImplBase, IMetaContainer
   {
      private readonly IWindsorContainer _container;

      /// <summary>
      /// Creates new adapter instance for provided Windsor container.
      /// </summary>
      /// <param name="container">Windsor container to be wrapped by <see cref="IMetaContainer"/>.</param>
      public CastleWindsorMetaContainerAdapter(IWindsorContainer container)
      {
         _container = container;
      }

      #region IMetaContainer Members
      public void Register(Type from, Type to, string name, Scope scope)
      {
         name = name ?? Guid.NewGuid().ToString();
         _container.AddComponentLifeStyle(name, from, to, Common.MapLifestyle(scope));         
      }

      public void Register(Type from, Func<string, object> factoryMethod, Scope scope)
      {
         Common.RegisterInKernel(_container.Kernel, from, factoryMethod, scope);
      }

      public IMetaContainer CreateChildContainer()
      {
         IWindsorContainer childContainer = new WindsorContainer();
         childContainer.Parent = _container;
         _container.AddChildContainer(childContainer);
         return new CastleWindsorMetaContainerAdapter(childContainer);
      }
      #endregion

      #region ServiceLocatorImplBase Members
      protected override IEnumerable<object> DoGetAllInstances(Type serviceType)
      {
         return (object[])_container.ResolveAll(serviceType, null);
      }

      protected override object DoGetInstance(Type serviceType, string key)
      {
         if (key != null)
         {
            if (!_container.Kernel.HasComponent(key))
            {
               Hashtable args = new Hashtable();
               args["key"] = key;
               return _container.Resolve(serviceType, args);
            }
            return _container.Resolve(key, serviceType);
         }
         return _container.Resolve(serviceType);
      }
      #endregion
   }
}
